package com.rfid.project.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;

import biz.util.*;

import com.rfid.project.model.*;
import com.rfid.project.dao.*;
import com.rfid.project.exception.CannotDelException;
import com.mysema.query.BooleanBuilder;

import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Service
@Transactional
public class ProjectTaskService {

	@Autowired
	private ProjectTaskDao projectTaskDao;

	private QProjectTask $ = QProjectTask.projectTask;

	@Autowired
	private ProjectTaskFinishApplyDao projectTaskFinishApplyDao;

	private QProjectTaskFinishApply $_projectTaskFinishApply = QProjectTaskFinishApply.projectTaskFinishApply;

	@Autowired
	private ProjectTaskDelayApplyDao projectTaskDelayApplyDao;

	private QProjectTaskDelayApply $_projectTaskDelayApply = QProjectTaskDelayApply.projectTaskDelayApply;

	@Autowired
	private ProjectTaskPersonDao projetTaskPersonDao;

	private QProjectTaskPerson $_projectTaskPerson = QProjectTaskPerson.projectTaskPerson;

	@Autowired
	public void setProjetTaskPersonDao(ProjectTaskPersonDao projetTaskPersonDao) {
		this.projetTaskPersonDao = projetTaskPersonDao;
	}

	@Autowired
	public void setProjectTaskDelayApplyDao(
			ProjectTaskDelayApplyDao projectTaskDelayApplyDao) {
		this.projectTaskDelayApplyDao = projectTaskDelayApplyDao;
	}

	@Autowired
	public void setProjectTaskDao(ProjectTaskDao projectTaskDao) {
		this.projectTaskDao = projectTaskDao;
	}

	@Autowired
	public void setProjectTaskFinishApplyDao(
			ProjectTaskFinishApplyDao projectTaskFinishApplyDao) {
		this.projectTaskFinishApplyDao = projectTaskFinishApplyDao;
	}

	public List<ProjectTask> findAll() {
		return ListUtil.toList(projectTaskDao.findAll());
	}

	public List<ProjectTask> findAll(Long projectId, Long taskCreatorId,
			Date taskCreateTimeBegin, Date taskCreateTimeEnd,
			Date planFinishDateBegin, Date planFinishDateEnd,
			Date actualFinishDateBegin, Date actualFinishDateEnd,
			String taskDescription, String status, Long projectTaskTypeId,
			String orderByAttribute) {
		BooleanBuilder condition = new BooleanBuilder();

		if (IdUtil.isNotEmpty(projectId)) {
			condition.and($.project.id.eq(projectId));
		}

		if (IdUtil.isNotEmpty(taskCreatorId)) {
			condition.and($.taskCreator.id.eq(taskCreatorId));
		}

		if (taskCreateTimeBegin != null) {
			condition.and($.taskCreateTime.after(taskCreateTimeBegin));
		}

		if (taskCreateTimeEnd != null) {
			condition.and($.taskCreateTime.before(taskCreateTimeEnd));
		}

		if (planFinishDateBegin != null) {
			condition.and($.planFinishDate.after(planFinishDateBegin));
		}

		if (planFinishDateEnd != null) {
			condition.and($.planFinishDate.before(planFinishDateEnd));
		}

		if (actualFinishDateBegin != null) {
			condition.and($.actualFinishDate.after(actualFinishDateBegin));
		}

		if (actualFinishDateEnd != null) {
			condition.and($.actualFinishDate.before(actualFinishDateEnd));
		}

		if (StringUtil.isNotEmpty(taskDescription)) {
			condition.and($.taskDescription.contains(taskDescription));
		}

		if (StringUtil.isNotEmpty(status)) {
			condition.and($.status.contains(status));
		}

		if (IdUtil.isNotEmpty(projectTaskTypeId)) {
			condition.and($.projectTaskType.id.eq(projectTaskTypeId));
		}

		return ListUtil.toList(projectTaskDao.findAll(condition));
	}

	public Page<ProjectTask> findAll(Long projectId, Long taskCreatorId,
			Date taskCreateTimeBegin, Date taskCreateTimeEnd,
			Date planFinishDateBegin, Date planFinishDateEnd,
			Date actualFinishDateBegin, Date actualFinishDateEnd,
			String taskDescription, String status, Long projectTaskTypeId,
			int pageNumber, int pageSize, String sortAttribute,
			String orderDirection) {
		BooleanBuilder condition = new BooleanBuilder();

		if (IdUtil.isNotEmpty(projectId)) {
			condition.and($.project.id.eq(projectId));
		}
		if (IdUtil.isNotEmpty(taskCreatorId)) {
			condition.and($.taskCreator.id.eq(taskCreatorId));
		}
		if (taskCreateTimeBegin != null) {
			condition.and($.taskCreateTime.after(taskCreateTimeBegin));
		}

		if (taskCreateTimeEnd != null) {
			condition.and($.taskCreateTime.before(taskCreateTimeEnd));
		}
		if (planFinishDateBegin != null) {
			condition.and($.planFinishDate.after(planFinishDateBegin));
		}

		if (planFinishDateEnd != null) {
			condition.and($.planFinishDate.before(planFinishDateEnd));
		}
		if (actualFinishDateBegin != null) {
			condition.and($.actualFinishDate.after(actualFinishDateBegin));
		}

		if (actualFinishDateEnd != null) {
			condition.and($.actualFinishDate.before(actualFinishDateEnd));
		}
		if (StringUtil.isNotEmpty(taskDescription)) {
			condition.and($.taskDescription.contains(taskDescription));
		}
		if (StringUtil.isNotEmpty(status)) {
			condition.and($.status.contains(status));
		}
		if (IdUtil.isNotEmpty(projectTaskTypeId)) {
			condition.and($.projectTaskType.id.eq(projectTaskTypeId));
		}

		Sort sortObject = null;
		if (StringUtil.isEmpty(sortAttribute)) {
			sortObject = new Sort(Direction.DESC, "id");
		} else {
			sortObject = new Sort(Direction.fromStringOrNull(orderDirection),
					sortAttribute);
		}

		PageRequest pageRequest = new PageRequest(pageNumber - 1, pageSize,
				sortObject);
		return projectTaskDao.findAll(condition, pageRequest);
	}

	public ProjectTask getProjectTask(Long id) {
		return projectTaskDao.getOne(id);
	}

	public void deleteProjectTask(Long id) throws CannotDelException {
		if (findProjectTaskFinishApplyByProjectTask(id)) {
			throw new CannotDelException("有任务完结申请引用，无法删除！");
		} else if(findProjectTaskDelayByProjectTask(id)){
			throw new CannotDelException("有任务延期申请引用，无法删除！");
		} else if(findProjectTaskPersonByProjectTask(id)){
			throw new CannotDelException("有项目任务人员引用，无法删除！");
		} else {
			projectTaskDao.delete(id);
		}
	}

	private boolean findProjectTaskFinishApplyByProjectTask(Long projectTaskId) {
		BooleanBuilder condition = new BooleanBuilder();
		condition.and($_projectTaskFinishApply.projectTaskPerson.projectTask.id.eq(projectTaskId));
		return this.projectTaskFinishApplyDao.count(condition) > 0;
	}
	
	private boolean findProjectTaskDelayByProjectTask(Long projectTaskId){
		BooleanBuilder condition = new BooleanBuilder();
		condition.and(this.$_projectTaskDelayApply.projectTaskPerson.projectTask.id.eq(projectTaskId));
		return this.projectTaskDelayApplyDao.count(condition) > 0;
	}
	
	private boolean findProjectTaskPersonByProjectTask(Long projectTaskId){
		BooleanBuilder condition = new BooleanBuilder();
		condition.and(this.$_projectTaskPerson.projectTask.id.eq(projectTaskId));
		return this.projetTaskPersonDao.count(condition) > 0;
	}

	public void saveProjectTask(ProjectTask projectTask) {
		if(null == projectTask.getTaskCreateTime()){
			projectTask.setTaskCreateTime(DateUtil.nowDate());
		}
		projectTaskDao.save(projectTask);
	}

	public List<ProjectTask> findByProject(Project project){
		BooleanBuilder condition = new BooleanBuilder();
		condition.and($.project.eq(project));
		return ListUtil.toList(this.projectTaskDao.findAll(condition));
	}
	
	public Set<People> findCreatePeoplesByProjectTask(Project project) {
		BooleanBuilder condition = new BooleanBuilder();
		condition.and($.project.id.eq(project.getId()));
		List<ProjectTask> projectTasks = ListUtil.toList(this.projectTaskDao
				.findAll(condition));
		Set<People> peoples = new HashSet<People>();
		for (ProjectTask projectTask : projectTasks) {
			peoples.add(projectTask.getTaskCreator());
		}
		return peoples;
	}
	
	public boolean findWorkingByProject(Project project){
		BooleanBuilder condition = new BooleanBuilder();
		condition.and(this.$.project.id.eq(project.getId()));
		condition.and(this.$.status.notIn(ProcessStatus.SUCCESS));
		return this.projectTaskDao.count(condition) > 0;
	}

	public void applyDelayProjectTask(ProjectTask projectTask) {
		ProjectTask source = this.projectTaskDao.findOne(projectTask.getId());
		source.setStatus(projectTask.getStatus());
		source.setPlanFinishDate(projectTask.getPlanFinishDate());
		source.setPlanWorktime(projectTask.getPlanWorktime());
		this.projectTaskDao.save(source);
	}

	public void applyFinishProjectTask(ProjectTask projectTask) {
		ProjectTask source = this.projectTaskDao.findOne(projectTask.getId());
		source.setStatus(projectTask.getStatus());
		source.setActualWorktime(projectTask.getActualWorktime());
		this.projectTaskDao.save(source);
	}

	public ProjectTask findOne(Long id) {
		return this.projectTaskDao.findOne(id);
	}

}
